var exp = require('express'),
  request = require('superagent'),
  bodyParser = require('body-parser'),
  logger = require('morgan'),
  url = require('url'),

  app = exp(),
  server,

  db = require('./db'),
  config = require('./config'),
  getPassword = require('./getPassword'),
  getVerifyCode = require('./getVerifyCode'),
  login = require('./login'),
  getSidCode = require('./getSidCode'),
  getVisitors = require('./getVisitors'),
  User = db.connection.model('user', db.UserModel);

//监听db close event并重新连接
db.connection.on('close', function () {

  console.log('db was closed, try open again.');

  db.openDb(function() {
    User = db.connection.model('user', db.UserModel);
  });

});

//基本设置
app.set('view engine', 'jade');
app.set('views', __dirname + '/views');
app.set('view cache', true);

app.use(bodyParser());
app.use(exp.static(__dirname + '/public'));
app.use(logger('short'));

//路由设置
app.get('/', function(req, res){
  res.render('index');
});

//获取被拦访客
app.post('/getVisitor/:mode?', function(req, mainRes){
  var qq = parseInt(req.body.qq),
    pass = req.body.pass,
    vcInput = req.body.vcInput.toUpperCase(),
    qvPage = req.body.qvPage, //分页参数

    data = {
      page: qvPage
    },
    md5Pass = getPassword(qq, pass, config.AB_VERIFYCODE),

    currentCount = 0,

    result = {
      status: 'failure',
      msg: '系统繁忙，请过段时间再尝试'
    };

  //获取更多被拦访客
  if(req.params.mode == 'loadMore'){
    result.mode = req.params.mode;
  }else{
    result.mode = '';
  };

  //假如是已经输入验证码的，先检查验证码后登录
  if(vcInput){

    //获取用户sig码
    User.findOne({account: qq})
      .exec(function(err, doc){

        if(doc && !!doc.sig){

          var sigHeaders = config.HEADERS;
          sigHeaders.Cookie = 'g_ut=3';
          sigHeaders.Referer = 'http://captcha.qq.com/cap_union_show?captype=3&aid=549000929&uin='+qq+'&cap_cd='+doc.cap_cd+'&v='+Math.random();
          sigHeaders.Host = config.GET_SIG_HOST;

          //检查验证码是否有误
          request.get(config.CHECK_VC_URL)
            .set(sigHeaders)
            .query({
              aid: config.LOGIN_PARAMS.aid,
              uin: qq,
              captype: 0,
              ans: vcInput,
              sig: doc.sig,
              r: Math.random()
            })
            .buffer()
            .end(function(res){

              var resArr = res.text.match(/rcode:(\d),randstr:\"(.*?)\",sig:\"(.*?)\"/),
                status = resArr[1],
                loginSig = resArr[3];

              if(status == 0){//验证码正确

                data.loginSig = loginSig;
                data.verifycode = vcInput;
                step2();

              }else{//res.text : cap_InnerCBVerify({rcode:5,randstr:"",sig:"",errmsg:"验证失败，请重试。"});

                result.msg = '验证失败，请重试。';
                result.type = 'refresh';
                mainRes.send(result);
              };

              console.log('check verifycode result : ' + res.text);

            });

        }else{//没有sig码肯定是错误的

          mainRes.send(result);

        };
      });

  }else{

    //开始工作，从第一步开始
    step1();
  };

  // 第一步：获取验证码和cookie
  function step1(){

    //本次查询次数过多，取消进入循环
    if(++currentCount >= config.TIMEOUT_COUNT) return;

    result.step_error = 1;

    User.where('account', qq)
      .where('pass').in([pass, md5Pass])
      .limit(1)
      .exec(function(err, doc){

        if(doc && doc.length && !!doc[0].sid){//假如sid已存在，则直接获取访客

          //说明用户在cookie里保存了密码，不需要再加密密码了
          if(doc[0].pass == pass){
            md5Pass = pass;
          };

          data.sid = doc[0].sid;
          step4();

        }else{

          getVerifyCode({
            qq: qq,
            callback: step2,
            backData: data
          });

        };

        console.log('now login user : ' + qq);

      });

  };

  // 第二步：验证码存在则登录
  function step2(){

    if(!data.verifycode){
      return finalFn();
    };

    console.log('step1...[get verifycode]: \033[92m'+ data.verifycode +'\033[39m');

    result.step_error = 2;

    //需要获取验证码图片
    if(data.cap_cd){

      result.cap_cd = data.cap_cd;
      result.msg = '需要输入验证码';
      mainRes.send(result);
    }else{

      login({
        verifycode: data.verifycode,
        qq: qq,
        pass: pass,
        cookies: data.cookies,
        callback: step3,
        backData: data,
        loginSig: data.loginSig || ''
      });

    };
  };

  // 第三步：根据登陆后的首页获取sid码
  function step3(){

    //帐号或密码错误
    if(data.loginErr == 3){

      result.type = 'refresh';
      result.msg = '帐号或密码错误';

    }else if(data.loginErr == 4 && data.cap_cd){

      result.type = 'refresh';
      result.msg = '您输入的验证码不正确，请重新输入。';

    };

    if(!data.loginedUrl){

      console.log('\033[31merror account or password\033[39m, qq is ' + qq);

      return finalFn();
    };

    console.log('step2...[login and get loginedUrl]: \033[92m'+ data.loginedUrl +'\033[39m');

    result.step_error = 3;

    getSidCode({
      loginedUrl: data.loginedUrl,
      callback: step4,
      backData: data
    });

  };

  // 第四步：成功返回被拦截访客列表
  function step4(){

    if(!data.sid){
      return finalFn();
    };

    console.log('step3...[get sid]: \033[92m'+ data.sid +'\033[39m');

    result.step_error = 4;

    getVisitors({
      qq: qq,
      sid: data.sid,
      callback: finalFn,
      backData: data,
      mode: result.mode
    });

  };

  // 成功响应或者失败返回
  function finalFn(){
    var visitors, user;

    if(data.visitors){
      visitors = data.visitors;

      //code -11334 系统繁忙，sid失效
      if(visitors.code != 0 || visitors.subcode != 0 || visitors.message != ''){

        //sid失效，重新获取
        console.log('step finally...[error]: \033[31mreturn step 1\033[39m');

        User.remove({account: qq}, function(err){
          console.log('clear user message: ' + (err ? '\033[31merror\033[39m' : '\033[92mok\033[39m') );
        });

        return step1();

      }else{

        console.log('step finally...[get visitors]: \033[92m'+ (result.mode || 'normal' ) +' mode\033[39m');

        //保存用户sid信息
        user = {
          account: qq,
          pass: md5Pass,
          sid: data.sid,
          date: + new Date()
        };

        User.update(
          {account: qq},
          user,
          {upsert: true},
          function(err){
            console.log('save user message: ' + (err ? '\033[31merror\033[39m' : '\033[92m'+ qq +'\033[39m') );
          }
        );

      };

      result.step_error = 0;
      result.status = 'success';
      result.msg = '获取被拦访客成功';
      result.visitors = visitors;
      result.qq = qq;
      result.pass = md5Pass;
      result.page = data.page;//翻页使用参数

    };

    result.errmsg = data.errorMsg || '';

    mainRes.send(result);
  };

});

//突破防盗链获取QQ用户头像
app.get('/getFace', function(req, faceRes){
  var faceUrl = req.query.faceUrl,
    tmpUrl = url.parse(faceUrl);

  request.get(faceUrl)
    .set('Host', tmpUrl.hostname)
    .end(function(res){
      res.pipe(faceRes);
    });

});

//需要输入验证码，获取验证码图片
app.get('/getVerifycodeImg', function(req, vcRes){
  var qq = req.query.qq,
    cap_cd = req.query.cap_cd,
    headers = config.HEADERS,
    sigReg = /\".*\"/;

  headers.Cookie = 'g_ut=3';
  headers.Referer = 'http://captcha.qq.com/cap_union_show?captype=3&aid=549000929&uin='+qq+'&cap_cd='+cap_cd+'&r='+Math.random();
  headers.Host = config.GET_SIG_HOST;

  //得到SIG码
  request.get(config.GET_SIG_URL)
    .query({
      uin: qq,
      aid: config.LOGIN_PARAMS.aid,
      r: Math.random()
    })
    .set(headers)
    .buffer()
    .end(function(res){

      var sigTmp = res.text.match(sigReg)[0],
        sig = sigTmp.split('"')[1],
        user;

      console.log('sig text : ' + res.text);

      //储存用户sig码
      user = {
        account: qq,
        sig: sig,
        cap_cd: cap_cd,
        date: + new Date()
      };

      User.update(
        {account: qq},
        user,
        {upsert: true},
        function(err){
          console.log('save user sig: ' + (err ? '\033[31merror\033[39m' : '\033[92m'+ sig +'\033[39m') );
        }
      );

      //得到验证码图片
      request.get(config.GET_VC_URL)
        .query({
          uin: qq,
          aid: config.LOGIN_PARAMS.aid,
          sig: sig
        })
        .set(headers)
        .end(function(res){

          res.pipe(vcRes);

        });
    });
});

server = app.listen(config.IS_LOCAL ? 3000 : config.SERVER_PORT, function() {

  console.log('Listening on port %d', server.address().port);

});

process.on('SIGTERM', function () {

	server.close(function () {

			process.exit(0);

	});

});